﻿using SqlSugar;
using SqlSugar.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Zhao.Common.Helper;
using Zhao.Repository.UnitOfWork;


namespace Zhao.Repository.Base
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new ()
    {
        protected const int _cacheSeconds = 120;
        private readonly IUnitOfWork _unitOfWork;
        private SqlSugarClient Context;
        public BaseRepository(IUnitOfWork unitOfWork)
        {
           Context = unitOfWork.GetDbClient();
        }

        #region 同步

        #region 查询

        public TEntity Query<T>(T primaryKey, bool blnUseCache = false)
        {
            return Context.Queryable<TEntity>().WithCacheIF(blnUseCache, _cacheSeconds).InSingle(primaryKey);
        }
        public TEntity Query(Expression<Func<TEntity, bool>> expression, bool blnUseCache = false)
        {
            return Context.Queryable<TEntity>().WhereIF(expression != null, expression).WithCacheIF(blnUseCache, _cacheSeconds).First();
        }


        public TEntity QueryOrder(Expression<Func<TEntity, bool>> expression, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return Context.Queryable<TEntity>().WhereIF(expression != null, expression).OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds).WithCacheIF(blnUseCache, _cacheSeconds).First();
        }

        public TEntity QueryParameterOrder(string strWhere, SugarParameter[] parameters, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return Context.Queryable<TEntity>().WhereIF(!strWhere.IsNullOrEmpty(), strWhere, parameters).OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds).WithCacheIF(blnUseCache, _cacheSeconds).First();
        }

        public List<TEntity> QueryList(Expression<Func<TEntity, bool>> expression, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return Context.Queryable<TEntity>()
                 .WhereIF(expression != null, expression)
                 .OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds)
                 .WithCacheIF(blnUseCache, _cacheSeconds)
                 .ToList();
        }

        public List<TEntity> QueryList(Expression<Func<TEntity, bool>> expression, int top, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return Context.Queryable<TEntity>()
                 .WhereIF(expression != null, expression)
                 .OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds)
                 .Take(top)
                 .WithCacheIF(blnUseCache, _cacheSeconds)
                 .ToList();
        }

        public PageModel<TEntity> QueryPage(Expression<Func<TEntity, bool>> where, string strOrderByFileds = null, int intPageIndex = 1, int intPageSize = 20)
        {
            int totalCount = 0;
            int totalPage = 0;
            var list = Context.Queryable<TEntity>()
             .OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds)
             .WhereIF(where != null, where)
             .ToPageList(intPageIndex, intPageSize, ref totalCount, ref totalPage);

            return new PageModel<TEntity>() { count = totalCount, PageCount = totalPage, PageIndex = intPageIndex, PageSize = intPageSize, data = list, code = totalCount == 0 ? -1 : 0, msg = totalCount == 0 ? "未查询到任何数据" : "" };
        }

        public int QueryCount(Expression<Func<TEntity, bool>> whereExpression)
        {
            return Context.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).Count();
        }
        #endregion

        #region 添加

        public int Add(TEntity entity)
        {
            return Context.Insertable<TEntity>(entity).ExecuteReturnIdentity();
        }

        public int Add(List<TEntity> entities)
        {
            return Context.Insertable(entities.ToArray()).ExecuteCommand();
        }

        #endregion

        #region 修改
        public bool Update(TEntity entity)
        {
            return Context.Updateable(entity).ExecuteCommandHasChange();
        }

        public bool Update(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> where)
        {
            return Context.Updateable<TEntity>().SetColumns(columns).Where(where).ExecuteCommandHasChange();
        }

        public int Update(List<TEntity> entities)
        {
            return Context.Updateable(entities.ToArray()).ExecuteCommand();
        }
        #endregion

        #region 删除
        public bool Delete<T>(T primaryKey)
        {
            return Context.Deleteable<TEntity>().In(primaryKey).ExecuteCommandHasChange();
        }

        public bool Delete(TEntity entity)
        {
            return Context.Deleteable<TEntity>(entity).ExecuteCommandHasChange();
        }

        public int Delete(object[] primaryKeys)
        {
            return Context.Deleteable<TEntity>().In(primaryKeys).ExecuteCommand();
        }

        public int Delete(Expression<Func<TEntity, bool>> where)
        {
            return Context.Deleteable<TEntity>().Where(where).ExecuteCommand();
        }

        #endregion


        #endregion

        #region 异步
        #region 查询

        public async Task<TEntity> QueryAsync<T>(T primaryKey, bool blnUseCache = false)
        {
            return await Context.Queryable<TEntity>().WithCacheIF(blnUseCache, _cacheSeconds).In(primaryKey).SingleAsync().ConfigureAwait(false);
        }

        public async Task<TEntity> QueryAsync(Expression<Func<TEntity, bool>> expression, bool blnUseCache = false)
        {
            return await Context.Queryable<TEntity>().WhereIF(expression != null, expression).WithCacheIF(blnUseCache, _cacheSeconds).FirstAsync().ConfigureAwait(false);
        }

        public async Task<TEntity> QueryOrderAsync(Expression<Func<TEntity, bool>> expression, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return await Context.Queryable<TEntity>().WhereIF(expression != null, expression).OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds).WithCacheIF(blnUseCache, _cacheSeconds).FirstAsync().ConfigureAwait(false);
        }

        public async Task<List<TEntity>> QueryListAsync(Expression<Func<TEntity, bool>> expression, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return await Context.Queryable<TEntity>()
                 .WhereIF(expression != null, expression)
                 .OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds)
                 .WithCacheIF(blnUseCache, _cacheSeconds)
                 .ToListAsync().ConfigureAwait(false);
        }

        public async Task<List<TEntity>> QueryListAsync(Expression<Func<TEntity, bool>> expression, int top, string strOrderByFileds = null, bool blnUseCache = false)
        {
            return await Context.Queryable<TEntity>()
                 .WhereIF(expression != null, expression)
                 .OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds)
                 .Take(top)
                 .WithCacheIF(blnUseCache, _cacheSeconds)
                 .ToListAsync().ConfigureAwait(false);
        }

        public async Task<PageModel<TEntity>> QueryPageAsync(Expression<Func<TEntity, bool>> where, string strOrderByFileds = null, int intPageIndex = 1, int intPageSize = 20)
        {
            RefAsync<int> totalCount = 0;

            var list = await Context.Queryable<TEntity>()
             .OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds)
             .WhereIF(where != null, where)
             .ToPageListAsync(intPageIndex, intPageSize, totalCount).ConfigureAwait(false);

            int totalPage = (Math.Ceiling(totalCount.ObjToDecimal() / intPageSize.ObjToDecimal())).ObjToInt();
            return new PageModel<TEntity>() { count = totalCount, PageCount = totalPage, PageIndex = intPageIndex, PageSize = intPageSize, data = list, code = totalCount == 0 ? -1 : 0, msg = totalCount == 0 ? "未查询到任何数据" : "" };
        }
        public async Task<int> QueryCountAsync(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Context.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).CountAsync().ConfigureAwait(false);
        }

        /// <summary> 
        ///查询-多表查询
        /// </summary> 
        /// <typeparam name="T">实体1</typeparam> 
        /// <typeparam name="T2">实体2</typeparam> 
        /// <typeparam name="T3">实体3</typeparam>
        /// <typeparam name="TResult">返回对象</typeparam>
        /// <param name="joinExpression">关联表达式 (join1,join2) => new object[] {JoinType.Left,join1.UserNo==join2.UserNo}</param> 
        /// <param name="selectExpression">返回表达式 (s1, s2) => new { Id =s1.UserNo, Id1 = s2.UserNo}</param>
        /// <param name="whereLambda">查询表达式 (w1, w2) =>w1.UserNo == "")</param> 
        /// <param name="strOrderByFileds"></param> 
        /// <param name="intPageIndex"></param> 
        /// <param name="intPageSize"></param> 
        /// <returns>值</returns>
        //public async Task<PageModel<TResult>> QueryMuchAsync<T, T2, T3, TResult>(
        //    Expression<Func<T, T2, T3, object[]>> joinExpression,
        //    Expression<Func<T, T2, T3, TResult>> selectExpression,
        //    Expression<Func<T, T2, T3, bool>> where = null,
        //    string strOrderByFileds = null,
        //    int intPageIndex = 1,
        //    int intPageSize = 20)
        //{
        //    RefAsync<int> totalCount = 0;
        //    var list = await Context.Queryable(joinExpression)
        //         .OrderByIF(!strOrderByFileds.IsNullOrWhiteSpace(), strOrderByFileds)
        //         .WhereIF(where != null, where)
        //         .Select(selectExpression)
        //         .ToPageListAsync(intPageIndex, intPageSize, totalCount);

        //    int totalPage = (Math.Ceiling(totalCount.ObjToDecimal() / intPageSize.ObjToDecimal())).ObjToInt();

        //    return new PageModel<TResult>() { count = totalCount, PageCount = totalPage, PageIndex = intPageIndex, PageSize = intPageSize, data = list, code = totalCount == 0 ? -1 : 0, msg = totalCount == 0 ? ResData.PageEmpty : "" };
        //}

        #endregion

        #region 添加

        public async Task<int> AddAsync(TEntity entity)
        {
            return await Context.Insertable<TEntity>(entity).ExecuteReturnIdentityAsync().ConfigureAwait(false);
        }

        public async Task<int> AddAsync(List<TEntity> entities)
        {
            return await Context.Insertable(entities.ToArray()).ExecuteCommandAsync().ConfigureAwait(false);
        }

        #endregion

        #region 修改
        public async Task<bool> UpdateAsync(TEntity entity)
        {
            return await Context.Updateable(entity).ExecuteCommandHasChangeAsync().ConfigureAwait(false);
        }

        public async Task<bool> UpdateAsync(Expression<Func<TEntity, TEntity>> columns, Expression<Func<TEntity, bool>> where)
        {
            return await Context.Updateable<TEntity>().SetColumns(columns).Where(where).ExecuteCommandHasChangeAsync().ConfigureAwait(false);
        }

        public async Task<int> UpdateAsync(List<TEntity> entities)
        {
            return await Context.Updateable(entities.ToArray()).ExecuteCommandAsync().ConfigureAwait(false);
        }
        #endregion

        #region 删除
        public async Task<bool> DeleteAsync<T>(T primaryKey)
        {
            return await Context.Deleteable<TEntity>().In(primaryKey).ExecuteCommandHasChangeAsync().ConfigureAwait(false);
        }

        public async Task<bool> DeleteAsync(TEntity entity)
        {
            return await Context.Deleteable<TEntity>().ExecuteCommandHasChangeAsync().ConfigureAwait(false);
        }

        public async Task<int> DeleteAsync(object[] ids)
        {
            return await Context.Deleteable<TEntity>().In(ids).ExecuteCommandAsync().ConfigureAwait(false);
        }

        public async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> where)
        {
            return await Context.Deleteable<TEntity>().Where(where).ExecuteCommandAsync().ConfigureAwait(false);
        }

        #endregion
        #endregion

    }

}
